﻿using System.Collections.Generic;
using Moq;
using NUnit.Framework;
using SessionHunter.Business;
using SessionHunter.Model;
using SessionHunter.UnitTests.Business;
using SessionHunter.ViewModel;

namespace SessionHunter.UnitTests.ViewModel
{
    [TestFixture]
    public class TestReferencesViewModel : TestBase
    {
        [Test]
        public void AddReferencedAssembliesToMissingAssemblies_TestErrorDoesNothing_Return()
        {
            // Assemble
            var mainViewModel = new Mock<ReferencesViewModel>() { CallBase = true };
            mainViewModel.Object.CurrentReferences_SelectedItem = null;

            // Act
            mainViewModel.Object.AddReferencedAssembliesToMissingAssemblies();

            // Assert
            mainViewModel.VerifyGet(mock => mock.CurrentReferenceManager, Times.Never(), "CurrentReferenceManager should not have been called");
        }

        [Test]
        public void AddReferencedAssembliesToMissingAssemblies_HasNoExternalReference_NoMissingAssemblies()
        {
            // Assemble
            var currentReference = new ExternalReference()
            {
                FullAssemblyName = TestReferenceManager.FakeFullName,
                Path = TestReferenceManager.FakePath
            };

            var referenceViewModel = new Mock<ReferencesViewModel>() { CallBase = true };
            referenceViewModel.Object.CurrentReferences_SelectedItem = currentReference;
            referenceViewModel.Object.MissingAssemblies = null;

            var referenceManager = new Mock<ReferenceManager>() { CallBase = true };
            referenceManager.Setup(mock => mock.GetReferencedAssemblies(currentReference)); // Return nothing

            referenceViewModel.SetupGet(mock => mock.CurrentReferenceManager).Returns(referenceManager.Object);

            // Act
            referenceViewModel.Object.AddReferencedAssembliesToMissingAssemblies();

            // Assert
            Assert.IsNull(referenceViewModel.Object.MissingAssemblies, "Something was added to missing assemblies when we didn't expect it");
        }

        [Test]
        public void AddReferencedAssembliesToMissingAssemblies_HasExternalReference_AddedToMissingAssemblies()
        {
            // Assemble
            var currentReference = new ExternalReference()
            {
                FullAssemblyName = TestReferenceManager.FakeFullName,
                Path = TestReferenceManager.FakePath
            };

            const string externalFakeName = @"AnotherAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

            var referenceViewModel = new Mock<ReferencesViewModel>() { CallBase = true };
            referenceViewModel.Setup(mock => mock.MissingAssemblies);
            referenceViewModel.Object.CurrentReferences_SelectedItem = currentReference;

            // Create a reference manager to return
            var referenceManager = new Mock<ReferenceManager>() { CallBase = true };
            referenceManager.Setup(mock => mock.GetReferencedAssemblies(currentReference)).Returns(() =>
            {
                var list = new List<string>();
                list.Add(externalFakeName);
                return list;
            });

            // Return our fake reference manager
            referenceViewModel.SetupGet(mock => mock.CurrentReferenceManager).Returns(referenceManager.Object);

            // Act
            referenceViewModel.Object.AddReferencedAssembliesToMissingAssemblies();

            // Assert
            // UNDONE: Tried this, but it raises an error
            // referenceViewModel.VerifySet(mock => mock.MissingAssemblies = It.IsAny<ObservableCollection<string>>(), Times.Once(), "Missing Assemblies Not Set");
            // This works, but raises an obsolete warning
            // referenceViewModel.VerifySet(mock => mock.MissingAssemblies, "Missing Assemblies Not Set");
        }
    }
}
